package algos;

import graph.Event;
import graph.Group;
import graph.SchoolYear;
import org.jgrapht.*;
import org.jgrapht.graph.*;
import graph.User;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Set;
import org.jgrapht.alg.NeighborIndex;
import view.View;

/**
 *
 * @author sanichan
 */
public class AlgoInference {
    
    private UndirectedGraph<Object, DefaultEdge> g;
    private ArrayList<ProbaObject> tabProb;
    private NeighborIndex tabVoisin;
    private View view;

    
    public AlgoInference(UndirectedGraph<Object, DefaultEdge> UserGraph, View v) {
        this.g = UserGraph;
        this.tabVoisin = new NeighborIndex(UserGraph);
        this.view = v;
    }
    
    public void initProb(){
        this.tabProb = new ArrayList<ProbaObject>();
    }
    
   public void BasicForSchool(User arg){
     ProbaObject po;
     Float nbTotal = 0.0f;
     User u; 
     
     initProb();
     
    Iterator it_users = g.vertexSet().iterator();
     
     
     while(it_users.hasNext())
     {
        Object obj = it_users.next();  

        if(obj.getClass().equals(User.class))
        {
            u = (User)obj;
            if (!u.getId_user().equals(arg.getId_user())){            
            
                Iterator it_schoolyear = u.getCursus().iterator();

                while (it_schoolyear.hasNext())
                {
                    SchoolYear sy = (SchoolYear)it_schoolyear.next();
                    po = new ProbaObject(sy.getNomEcole(), 0.0f);

                    if(!tabProb.contains(po)){
                        tabProb.add(po);
                    }
                    else{
                        tabProb.get(tabProb.indexOf(po)).incremementNbObj();
                        nbTotal ++ ;
                    }          
                }
            }
         }
     }
         
    // Parcours de la table afin de calculer les probas
    Iterator it_prob = tabProb.iterator();
    
    while (it_prob.hasNext())
    {
        po = (ProbaObject)it_prob.next();
        po.calcProb(nbTotal);
    }
     
     if(!tabProb.isEmpty())
     {
        Collections.sort(tabProb, new ComparateurProba());

        view.displayAlgoAnswer(tabProb.get(0).toString() + "\n" 
                + tabProb.get(1).toString() + "\n" 
                + tabProb.get(2).toString());
     }
   }
    
   
     public void BasicForSpecialite(User arg){
     ProbaObject po;
     Float nbTotal = 0.0f;
     User u; 
     
     initProb();
       
     Iterator it_users = g.vertexSet().iterator();
     
     while(it_users.hasNext())
     {
        Object obj = it_users.next();  

        if(obj.getClass().equals(User.class))
        {
            u = (User)obj;
            if (!u.getId_user().equals(arg.getId_user())){
                Iterator it_schoolyear = u.getCursus().iterator();

                while (it_schoolyear.hasNext()){
                    SchoolYear sy = (SchoolYear)it_schoolyear.next();
                        if (sy.getNomEcole().equalsIgnoreCase("Institut National des Sciences Appliquées de Toulouse")){                                
                            if(!sy.getSpecialite().equalsIgnoreCase("0")){
                                po = new ProbaObject(sy.getSpecialite(), 0.0f);
                                if(!tabProb.contains(po)){
                                    tabProb.add(po);
                                }
                                else{
                                    tabProb.get(tabProb.indexOf(po)).incremementNbObj();
                                    nbTotal ++ ;
                                }
                            }    
                        } 
                }
            }
         }
     }
     
    // Parcours de la table afin de calculer les probas
    Iterator it_prob = tabProb.iterator();
    
    while (it_prob.hasNext())
    {
        po = (ProbaObject)it_prob.next();
        po.calcProb(nbTotal);
    }
     
     if(!tabProb.isEmpty())
     {
        Collections.sort(tabProb, new ComparateurProba());

        view.displayAlgoAnswer(tabProb.get(0).toString() + "\n" 
                + tabProb.get(1).toString() + "\n" 
                + tabProb.get(2).toString());
     }
   }
 
       
    public void AGGForSchool(User u){
        
        User friend;
        Iterator it_neighbors = tabVoisin.neighborListOf(u).iterator();
        ProbaObject po;
        Float nbTotal = 0.0f;
        
        initProb();
        
        //Parcours des amis
        while(it_neighbors.hasNext()){

            Object obj = it_neighbors.next();  
            
            if(obj.getClass().equals(User.class))
            {
                friend = (User)obj;
                //System.out.println("J'ai un copain!!" + friend);

                Iterator it_schoolyear = friend.getCursus().iterator();

                while (it_schoolyear.hasNext())
                {
                    SchoolYear sy = (SchoolYear)it_schoolyear.next();
                    po = new ProbaObject(sy.getNomEcole(), 0.0f);
                    
                    if(!tabProb.contains(po)){
                        tabProb.add(po);
                    }
                    else{
                        tabProb.get(tabProb.indexOf(po)).incremementNbObj();
                        nbTotal ++ ;
                    }                 
                }
            }                
        }
        
        // Parcours de la table afin de calculer les probas
      
        Iterator it_prob = tabProb.iterator();
        while (it_prob.hasNext()){
            po = (ProbaObject)it_prob.next();
            po.calcProb(nbTotal);
        }
        
     if(!tabProb.isEmpty())
     {
        Collections.sort(tabProb, new ComparateurProba());
        
        view.displayAlgoAnswer(tabProb.get(0).toString() + "\n" 
                + tabProb.get(1).toString() + "\n" 
                + tabProb.get(2).toString());
     }
  }
    
    public void AGGForSpecialite(User u){
        
        User friend;
        Iterator it_neighbors = tabVoisin.neighborListOf(u).iterator();
        ProbaObject po;
        Float nbTotal = 0.0f;
        
        initProb();
        
        //Parcours des amis
        while(it_neighbors.hasNext()){

            Object obj = it_neighbors.next();  
            
            if(obj.getClass().equals(User.class))
            {
                friend = (User)obj;
                //System.out.println("J'ai un copain!!" + friend);

                Iterator it_schoolyear = friend.getCursus().iterator();

                while (it_schoolyear.hasNext())
                {
                    SchoolYear sy = (SchoolYear)it_schoolyear.next();
                    if (sy.getNomEcole().equalsIgnoreCase("Institut National des Sciences Appliquées de Toulouse")){                                
                        if(!sy.getSpecialite().equalsIgnoreCase("0")){
                            po = new ProbaObject(sy.getSpecialite(), 0.0f);
                            if(!tabProb.contains(po)){
                                tabProb.add(po);
                            }
                            else{
                                tabProb.get(tabProb.indexOf(po)).incremementNbObj();
                                nbTotal ++ ;
                            }
                        }
                    }
                }
            }                
        }
        
        // Parcours de la table afin de calculer les probas
      
        Iterator it_prob = tabProb.iterator();
        while (it_prob.hasNext()){
            po = (ProbaObject)it_prob.next();
            po.calcProb(nbTotal);
        }
        
        
        // tri et affichage de la liste de ProbaObject
     if(!tabProb.isEmpty())
     {
        Collections.sort(tabProb, new ComparateurProba());
        
        view.displayAlgoAnswer(tabProb.get(0).toString() + "\n" 
                + tabProb.get(1).toString() + "\n" 
                + tabProb.get(2).toString());
     }
  
    }       
       public void CliqueForSchool(User u){
        
        User friend;
        Iterator it_neighbors = tabVoisin.neighborListOf(u).iterator();
        ProbaObject po;
        Float nbTotal = 0.0f;
        
        initProb();
        
        //Parcours de mes voisins
        while(it_neighbors.hasNext()){

            Object obj1 = it_neighbors.next();  
            //Si mon voisin est un user
            if(obj1.getClass().equals(User.class))
            {
                friend = (User)obj1;
                //System.out.println("J'ai un copain!!" + friend);

                Iterator it_schoolyear = friend.getCursus().iterator();

                while (it_schoolyear.hasNext())
                {
                    SchoolYear sy = (SchoolYear)it_schoolyear.next();
                    po = new ProbaObject(sy.getNomEcole(), 0.0f);
                    
                    if(!tabProb.contains(po)){
                        tabProb.add(po);
                    }
                    else{
                        tabProb.get(tabProb.indexOf(po)).incremementNbObj();
                        nbTotal ++ ;
                    }                 
                }
           // Si c'est un groupe, je parcours les voisins
            } else if (obj1.getClass().equals(Group.class)){
                Iterator it_members = tabVoisin.neighborListOf(obj1).iterator();
                while (it_members.hasNext()){
                    Object obj2 = it_members.next();  
                    //si le voisin est un user et que ce n'est pas déjà un ami
                    if(obj2.getClass().equals(User.class) 
                            && !(tabVoisin.neighborListOf(u).contains(obj2))
                            && !(obj2.equals(u)))
                    {
                        friend = (User)obj2;
                        //System.out.println("J'ai un copain!!" + friend);

                        Iterator it_schoolyear = friend.getCursus().iterator();

                        while (it_schoolyear.hasNext())
                        {
                            SchoolYear sy = (SchoolYear)it_schoolyear.next();
                            po = new ProbaObject(sy.getNomEcole(), 0.0f);

                            if(!tabProb.contains(po)){
                                tabProb.add(po);
                            }
                            else{
                                tabProb.get(tabProb.indexOf(po)).incremementNbObj();
                                nbTotal ++ ;
                            }                 
                        }
                    }
            }                 
        
        
        // Parcours de la table afin de calculer les probas
      
        Iterator it_prob = tabProb.iterator();
        while (it_prob.hasNext()){
            po = (ProbaObject)it_prob.next();
            po.calcProb(nbTotal);
        }
        
         if(!tabProb.isEmpty())
         {
            Collections.sort(tabProb, new ComparateurProba());

            view.displayAlgoAnswer(tabProb.get(0).toString() + "\n" 
                    + tabProb.get(1).toString() + "\n" 
                    + tabProb.get(2).toString());
         }
      }
   }
}

       public void CliqueForSpecialite(User u){
        
        User friend;
        Iterator it_neighbors = tabVoisin.neighborListOf(u).iterator();
        ProbaObject po;
        Float nbTotal = 0.0f;
        
        initProb();
        
        //Parcours de mes voisins
        while(it_neighbors.hasNext()){

            Object obj1 = it_neighbors.next();  
            //Si mon voisin est un user
            if(obj1.getClass().equals(User.class))
            {
                friend = (User)obj1;
                //System.out.println("J'ai un copain!!" + friend);

                Iterator it_schoolyear = friend.getCursus().iterator();

                while (it_schoolyear.hasNext())
                {
                    SchoolYear sy = (SchoolYear)it_schoolyear.next();
                    if (sy.getNomEcole().equalsIgnoreCase("Institut National des Sciences Appliquées de Toulouse")){                                
                        if(!sy.getSpecialite().equalsIgnoreCase("0")){
                            po = new ProbaObject(sy.getSpecialite(), 0.0f);

                            if(!tabProb.contains(po)){
                                tabProb.add(po);
                            }
                            else{
                                tabProb.get(tabProb.indexOf(po)).incremementNbObj();
                                nbTotal ++ ;
                            }
                        }
                    }                 
                }
           // Si c'est un groupe, je parcours les voisins
            } else if (obj1.getClass().equals(Group.class)){
                Iterator it_members = tabVoisin.neighborListOf(obj1).iterator();
                while (it_members.hasNext()){
                    Object obj2 = it_members.next();  
                    //si le voisin est un user et que ce n'est pas déjà un ami
                    if(obj2.getClass().equals(User.class) 
                            && !(tabVoisin.neighborListOf(u).contains(obj2))
                            && !(obj2.equals(u)))
                    {
                        friend = (User)obj2;
                        //System.out.println("J'ai un copain!!" + friend);

                        Iterator it_schoolyear = friend.getCursus().iterator();

                        while (it_schoolyear.hasNext())
                        {
                            SchoolYear sy = (SchoolYear)it_schoolyear.next();
                            if (sy.getNomEcole().equalsIgnoreCase("Institut National des Sciences Appliquées de Toulouse")){                                
                                if(!sy.getSpecialite().equalsIgnoreCase("0")){
                                    po = new ProbaObject(sy.getSpecialite(), 0.0f);
                                    if(!tabProb.contains(po)){
                                        tabProb.add(po);
                                    }
                                    else{
                                        tabProb.get(tabProb.indexOf(po)).incremementNbObj();
                                        nbTotal ++ ;
                                    }
                                }
                            }                 
                        }
                    }
            }                 
        
        
        // Parcours de la table afin de calculer les probas
      
        Iterator it_prob = tabProb.iterator();
        while (it_prob.hasNext()){
            po = (ProbaObject)it_prob.next();
            po.calcProb(nbTotal);
        }
        
         if(!tabProb.isEmpty())
         {
            Collections.sort(tabProb, new ComparateurProba());

            view.displayAlgoAnswer(tabProb.get(0).toString() + "\n" 
                    + tabProb.get(1).toString() + "\n" 
                    + tabProb.get(2).toString());
         }
      }
   }
}

       
      
    public void CliqueEventForSchool(User u){
        
        User friend;
        Iterator it_neighbors = tabVoisin.neighborListOf(u).iterator();
        ProbaObject po;
        Float nbTotal = 0.0f;
        
        initProb();
        
        //Parcours de mes voisins
        while(it_neighbors.hasNext()){

            Object obj1 = it_neighbors.next();  
            //Si mon voisin est un user
            if(obj1.getClass().equals(User.class))
            {
                friend = (User)obj1;
                //System.out.println("J'ai un copain!!" + friend);

                Iterator it_schoolyear = friend.getCursus().iterator();

                while (it_schoolyear.hasNext())
                {
                    SchoolYear sy = (SchoolYear)it_schoolyear.next();
                    po = new ProbaObject(sy.getNomEcole(), 0.0f);
                    
                    if(!tabProb.contains(po)){
                        tabProb.add(po);
                    }
                    else{
                        tabProb.get(tabProb.indexOf(po)).incremementNbObj();
                        nbTotal ++ ;
                    }                 
                }
           // Si c'est un groupe, je parcours les voisins
            } else if (obj1.getClass().equals(Event.class)){
                Iterator it_members = tabVoisin.neighborListOf(obj1).iterator();
                while (it_members.hasNext()){
                    Object obj2 = it_members.next();  
                    //si le voisin est un user et que ce n'est pas déjà un ami
                    if(obj2.getClass().equals(User.class) 
                            && !(tabVoisin.neighborListOf(u).contains(obj2))
                            && !(obj2.equals(u)))
                    {
                        friend = (User)obj2;
                        //System.out.println("J'ai un copain!!" + friend);

                        Iterator it_schoolyear = friend.getCursus().iterator();

                        while (it_schoolyear.hasNext())
                        {
                            SchoolYear sy = (SchoolYear)it_schoolyear.next();
                            po = new ProbaObject(sy.getNomEcole(), 0.0f);

                            if(!tabProb.contains(po)){
                                tabProb.add(po);
                            }
                            else{
                                tabProb.get(tabProb.indexOf(po)).incremementNbObj();
                                nbTotal ++ ;
                            }                 
                        }
                    }
            }                 
        
        
        // Parcours de la table afin de calculer les probas
      
        Iterator it_prob = tabProb.iterator();
        while (it_prob.hasNext()){
            po = (ProbaObject)it_prob.next();
            po.calcProb(nbTotal);
        }
        
         if(!tabProb.isEmpty())
         {
            Collections.sort(tabProb, new ComparateurProba());

            view.displayAlgoAnswer(tabProb.get(0).toString() + "\n" 
                    + tabProb.get(1).toString() + "\n" 
                    + tabProb.get(2).toString());
         }
      }
   }
}

    class ComparateurProba implements Comparator<ProbaObject> {
        public int compare(ProbaObject p1, ProbaObject p2){
            if (p1.getProb().compareTo(p2.getProb()) == 1){
                return -1;
            }else if (p1.getProb().compareTo(p2.getProb()) == -1){
                return 1;
            }else{
                return 0;
            }
        }
    }
}

